筆記目錄

Skip to content

淺談 .NET 預設 Logger 及其優化技巧

TLDR

  • .NET 預設已整合 Console、Debug 與 EventSource 等 Logger Provider。
  • 透過 appsettings.jsonLogLevel 區段,可針對不同命名空間或 Provider 設定精細的日誌過濾。
  • 使用 logger.IsEnabled(LogLevel) 可避免在日誌等級未啟用時,執行昂貴的資料運算。
  • 應優先使用結構化日誌(使用 {Placeholder}),而非字串串接,以提升效能並利於 ELK 等系統分析。
  • 若需在日誌中顯示大括號,必須使用雙大括號 進行轉義。
  • 建議使用 AddJsonConsole() 輸出結構化 JSON,以利於現代化日誌管理。

預設 Logger 機制與設定

WebApplication.CreateBuilder() 在初始化時會自動載入預設的 Logger Provider,包含 Console、Debug 及 EventSource。開發者可透過 builder.Logging 進行自訂,例如清除預設設定或加入特定 Provider。

什麼情況下會遇到這個問題:當專案需要調整預設的日誌輸出目的地(如僅輸出至 Console)或需要完全控制日誌來源時。

csharp
// 調整 LoggerProvider 的範例
WebApplicationBuilder builder = WebApplication.CreateBuilder(args);

builder.Logging.ClearProviders(); // 清除預設的 Provider
builder.Logging.AddConsole();     // 加入 Console Provider
builder.Logging.AddDebug();       // 加入 Debug Provider

使用 Appsettings.json 控制日誌等級

透過設定檔,可以針對特定命名空間(Namespace)或 Provider 設定不同的日誌等級。

什麼情況下會遇到這個問題:當生產環境中需要隱藏過多的 Debug 資訊,但又希望保留特定服務的 Warning 或 Error 紀錄時。

json
{
  "Logging": {
    "LogLevel": {
      "Default": "Information",
      "Microsoft.AspNetCore": "Warning",
      "LoggerTest.Services.TestService1": "Warning"
    }
  }
}
  • 外層 LogLevel 適用於所有 Provider。
  • 可使用萬用字元 * 進行批次設定,例如 "*.Services": "Warning"

效能優化:使用 Logger.IsEnabled

在產生日誌前若涉及昂貴的運算(如資料庫查詢),應先檢查該等級是否啟用。

什麼情況下會遇到這個問題:當日誌內容需要從資料庫撈取大量資料或進行複雜計算,且該日誌等級在生產環境通常是關閉的。

csharp
if (logger.IsEnabled(LogLevel.Information)) {
    // 僅在 Information 等級啟用時執行,避免浪費效能
    int processedRecords = await database.GetProcessedRecordsCount();
    logger.LogInformation("系統已完成資料更新,共處理 {Count} 筆資料。", processedRecords);
}

結構化日誌的優勢與實作

結構化日誌能避免字串串接帶來的效能損耗,並能將參數分離,利於後續的日誌分析工具(如 ELK)進行索引。

什麼情況下會遇到這個問題:當需要將日誌匯出至集中式管理系統,或希望提升應用程式在高負載下的日誌處理效能時。

正確的結構化寫法

避免使用字串相加,改用佔位符:

csharp
// 推薦寫法
logger.LogInformation("使用者 {UserId} 已登入系統,所屬部門: {Department}", user.Id, user.Department);

特殊字元處理

若日誌內容本身包含大括號,必須使用雙大括號進行轉義:

csharp
// 輸出結果為:這是一個 JSON 範例:{"name": "value"}
logger.LogInformation("這是一個 JSON 範例:{{\"name\": \"value\"}}");

輸出 JSON 格式

AddConsole() 替換為 AddJsonConsole(),可直接輸出結構化資料:

csharp
builder.Logging.AddJsonConsole();

異動歷程

  • 2025-03-23 初版文件建立。